package com.drpclub.gamebackend.common.utils;

import cn.hutool.core.io.FileTypeUtil;
import cn.hutool.core.lang.UUID;
import com.drpclub.gamebackend.exception.IgnoreException;
import com.drpclub.gamebackend.exception.MyAccessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Optional;

import static com.drpclub.gamebackend.common.constant.Const.INVALID_COOKIE_ACCESS;
import static com.drpclub.gamebackend.common.constant.Const.TOKEN;
import static com.drpclub.gamebackend.common.utils.JwtUtils.getTokenFromHeader;

/**
 * @author dongruipeng
 * @Descrpition
 * @date 2019year 12month12day  15:06:09
 */
@Slf4j
public class DrpUtils {

    public static <T> T isNotNull(T obj, String msg) {
        if (obj == null) {
            throw new IgnoreException (msg);
        } else {
            return obj;
        }
    }

    public static List arrayIsNotEmpty(List arr, String msg) {
        return arrayIsEmpty (arr, msg);
    }

    private static List arrayIsEmpty(List arr, String msg) {
        isNotNull (arr, msg);
        if (arr.size () == 0) {
            throw new ArrayIndexOutOfBoundsException (msg + " => The array length is empty");
        }
        return arr;
    }

    public static String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader ("x-forwarded-for");
        if (ip == null || ip.length () == 0 || "unknown".equalsIgnoreCase (ip)) {
            ip = request.getHeader ("Proxy-Client-IP");
        }
        if (ip == null || ip.length () == 0 || "unknown".equalsIgnoreCase (ip)) {
            ip = request.getHeader ("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length () == 0 || "unknown".equalsIgnoreCase (ip)) {
            ip = request.getRemoteAddr ();
        }
        if (!ip.isEmpty () && ip.indexOf (",") > 0) {
            ip = Optional.ofNullable (StringUtils.split (ip, ",")).orElse (new String[1])[0];
        }
        return ip;
    }

    public static String getHeader(String name, HttpHeaders headers) {
        List<String> value = headers.get (name);
        return CollectionUtils.isEmpty (value) ? null : value.get (0);
    }

    public static String verifyImageType(InputStream inputStream) {
        final String type = FileTypeUtil.getType (inputStream);
        if (!type.equals ("jpg") && !type.equals ("png")) {
            throw new MyAccessException ("wrong file type");
        }
        return type;
    }

    public static String getUserAgent(HttpServletRequest httpServletRequest) {
        final String agent = httpServletRequest.getHeader (HttpHeaders.USER_AGENT);
        return agent != null ? agent : "";
    }

    public static String getUrl(HttpServletRequest httpServletRequest) {
        final String queryString = httpServletRequest.getQueryString ();
        return httpServletRequest.getRequestURL ().toString ()
                + (queryString == null ? "" : "?" + queryString);
    }

    public static String getUsernameFromRequest(HttpServletRequest request) {
        String token = getToken (request);
        return token != null ? JwtUtils.getUsernameFromToken (token) : null;
    }

    public static String getToken(HttpServletRequest request) {
        String header = request.getHeader (HttpHeaders.AUTHORIZATION);
        return header != null ? getTokenFromHeader (header) : null;
    }

    public static boolean verifySecurityPath(List<String> permitPaths, String path) {
        if (permitPaths.contains (path)) return true;
        for (String permitPath : permitPaths) {
            if (path.startsWith (permitPath)) {
                return true;
            }
        }
        return false;
    }

    public static String getUsernameFromCookie(HttpServletRequest request) {
        final Optional<Cookie> cookie = getCookie (request, TOKEN);
        final Cookie c_ = cookie.orElseThrow (() -> new MyAccessException (INVALID_COOKIE_ACCESS));
        return JwtUtils.getUsernameFromToken (c_.getValue ());
    }


    public static HttpHeaders extractHttpHeaders(HttpServletRequest request) {
        final HttpHeaders headers = new HttpHeaders ();
        final Enumeration<String> headerNames = request.getHeaderNames ();
        while (headerNames.hasMoreElements ()) {
            String name = headerNames.nextElement ();
            final List<String> value = Collections.list (request.getHeaders (name));
            headers.put (name, value);
        }
        return headers;
    }

    public static String createRandomName() {
        return UUID.fastUUID ().toString (true).substring (0, 6);
    }


    public static void setCookie(HttpServletResponse response, String key, String name, int maxAge) {
        Cookie cookie = new Cookie (key, name);
        cookie.setMaxAge (maxAge);
        response.addCookie (cookie);
    }

    private static Optional<Cookie> getCookie(HttpServletRequest request, String name) {
        Cookie[] cookies = request.getCookies ();
        for (Cookie cookie : cookies) {
            if (cookie.getName ().equals (name)) {
                return Optional.of (cookie);
            }
        }
        return Optional.empty ();
    }

    public static void removeCookie(HttpServletResponse response, String name) {
        final Cookie cookie = new Cookie (name, "");
        cookie.setMaxAge (0);
        response.addCookie (cookie);
    }
}
